using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using NUnit.Framework;
using System.Web;
using System.Linq;
using System.Diagnostics;
using System.Xml;

namespace Legend.Web.QueryString.Tests.QueryStringSerializerTests
{
    public class QueryStringSerializerTestCase
    {
        protected QueryStringSerializer serializer;

        [SetUp]
        public void SetUp()
        {
            this.serializer = new QueryStringSerializer();
        }
    }

    [TestFixture]
    public class Serialize
        : QueryStringSerializerTestCase
    {
        [Test]
        public void should_serialize_collection_with_single_key_value_pair_correctly()
        {
            var d = new Dictionary<string, string> { { "a", "a" } };

            var query = this.serializer.Serialize(d);

            Assert.AreEqual("a=a", query);
        }

        [Test]
        public void should_separate_key_value_pairs_with_ampersand()
        {
            var d = new Dictionary<string, string> { { "a", "a" }, { "b", "b" } };
            
            var query = serializer.Serialize(d);

            Assert.AreEqual("a=a&b=b", query);
        }

        [Test]
        public void should_url_encode_keys()
        {
            var d = new Dictionary<string, string> { { "a a", "a" } };
         
            var query = serializer.Serialize(d);

            Assert.AreEqual("a+a=a", query);
        }

        [Test]
        public void should_url_encode_values()
        {
            var d = new Dictionary<string, string> { { "a", "a a" } };
            
            var query = serializer.Serialize(d);

            Assert.AreEqual("a=a+a", query);
        }

    }

    [TestFixture]
    public class Parse
        : QueryStringSerializerTestCase
    {
        [Test]
        public void should_return_empty_collection_when_query_string_is_null()
        {
            var result = this.serializer.Parse(null);

            Assert.AreEqual(0, result.Count());
        }

        [Test]
        public void should_return_empty_collection_when_query_is_empty_string()
        {
            var result = this.serializer.Parse(string.Empty);

            Assert.AreEqual(0, result.Count());
        }

        [Test]
        public void should_split_single_key_value_pairs()
        {
            var result = this.serializer.Parse("foo=1&bar=2").ToDictionary(k => k.Key, v => v.Value);

            Assert.AreEqual(2, result.Count);
            Assert.AreEqual("1", result["foo"]);
            Assert.AreEqual("2", result["bar"]);
        }

        [Test]
        public void should_url_decode_values()
        {
            var result = this.serializer.Parse("foo=a+a");
            Assert.AreEqual("a a", result.First().Value);
        }

        [Test]
        public void should_url_decode_keys()
        {
            var result = this.serializer.Parse("a+a=a");
            Assert.AreEqual("a a", result.First().Key);
        }

        [Test]
        public void should_return_empty_string_for_keys_with_no_value()
        {
            var result = this.serializer.Parse("a=&b=").ToDictionary(k => k.Key, v => v.Value);
            Assert.AreEqual(string.Empty, result["a"]);
            Assert.AreEqual(string.Empty, result["b"]);
        }

        [Test, ExpectedException(typeof(FormatException)), Ignore("Not done")]
        public void should_throw_exception_when_key_contains_ampersand()
        {
            var result = this.serializer.Parse("a&a=a");

            foreach (var value in result)
            {
                Debug.WriteLine(value.Key + " " + value.Value);
            }
        }
    }
}